home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 May: Tool Chest / Developer CD Series May 1996 (Tool Chest) (Apple Computer) (1996).iso / Sample Code / Snippets / Interapplication Communication / AECDEV⁄AEDAEMON / AECDEV.PPC.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-09  |  17.6 KB  |  380 lines  |  [TEXT/MPS ]

  1. /*------------------------------------------------------------------------------
  2. #
  3. #   Apple Developer Technical Support
  4. #
  5. #   AppleEvent Sample Control Panel Device
  6. #
  7. #   AECDEV
  8. #
  9. #   AECDEV.c  -   C Source
  10. #   Written by  C.K. Haun
  11. #
  12. #   Copyright © 1991 Apple Computer, Inc.
  13. #   All rights reserved.
  14. #
  15. #   Versions:   1.0                 8/91
  16. #
  17. #   Components: AECdev.p          August 2, 1991
  18. #               AECDEV.PPC.c      August 2, 1991
  19. #
  20. #   AECDEV demonstrates the techniques needed to send AppleEvents
  21. #   from a CDEV/DA/INIT/Driver.
  22. #   Requires the sample AEDaemon to work.
  23. #
  24. ------------------------------------------------------------------------------*/
  25. /*------------------------------------------------------------------------------
  26. #   This file contains the AppleEvent code that creates the
  27. #   AppleEvent,  and PPC toolbox code that finds and transfers the data to the 
  28. #   Backgrounder.
  29. #   It also contains the PBCatSearch code.
  30. ------------------------------------------------------------------------------*/
  31.  
  32. #include "AECdev.h"
  33. /* FindATarget prompts the user for a target application (through the PPC browser) */
  34. /* and a document for that application to open (with Standard File) */
  35. /* Once it's gotten that information, it bundles up the information about the */
  36. /* document to be opened into an APpleEvent list, adds the address of the target */
  37. /* application to the event, and passes the data to the routine that starts the PPC */
  38. /* transfer */
  39. void FindATarget(CDEVHnd storage)
  40. {
  41.     OSErr theErr = noErr;
  42.     LocationNameRec theLoc;
  43.     PortInfoRec theRec;
  44.     AEDesc theAddress, docDesc;
  45.     AEDescList theList;
  46.     AliasHandle myAlias;
  47.     StandardFileReply myReply;
  48.     TargetID theID;
  49.     AppleEvent theEvent;
  50.     Str32 tWext;
  51.     Str32 txWext;
  52.     /* Get the strings that will appear in the PPC browser */
  53.     GetIndString(&tWext, kStringsID, kBrowse1);
  54.     GetIndString(&txWext, kStringsID, kBrowse2);
  55.     /* Choose the Application you want to send the event to */
  56.     if (noErr == PPCBrowser(tWext, &txWext, false, &theLoc, &theRec, nil, nil)) {
  57.         /* Now I'll create the ODOC applevent */
  58.         /* Create the targetID for the selected application first */
  59.         theID.name = theRec.name;
  60.         theID.location = theLoc;
  61.         theErr = AECreateDesc(typeTargetID, (Ptr)&theID, sizeof(theID), &theAddress);
  62.         if (theErr == noErr) {
  63.         /* Create the whole event */
  64.             theErr = AECreateAppleEvent(kCoreEventClass, kAEOpenDocuments, &theAddress, kAutoGenerateReturnID, kAnyTransactionID,
  65.                                         &theEvent);
  66.             if (theErr == noErr) {
  67.                 /* now get a document to pass */
  68.                 StandardGetFile(nil, -1, nil, &myReply);
  69.                 if (myReply.sfGood) {
  70.                     /* odoc passed a list of FSSpecs, so make a list */
  71.                     /* even though this will only contain one spec, you still need a list */
  72.                     theErr = AECreateList(nil, 0, false, &theList);
  73.                     if (theErr == noErr) {
  74.                         /* create an alias out of the file spec */
  75.                         /* I'm not real sure why I did this, since there is a system coercion handler for */
  76.                         /* alias to FSSpec, but I'm paranoid (and goofy) */
  77.                         theErr = NewAlias(nil, &myReply.sfFile, &myAlias);
  78.                         if (theErr == noErr) {
  79.                             HLock((Handle)myAlias);
  80.                             /* now create an alias descriptor */
  81.                             theErr = AECreateDesc(typeAlias, (Ptr)*myAlias, GetHandleSize((Handle)myAlias), &docDesc);
  82.                             if (theErr == noErr) {
  83.                                 DisposHandle((Handle)myAlias);      /* no longer needed */
  84.                                 /* put it in the list */
  85.                                 theErr = AEPutDesc(&theList, 0, &docDesc);
  86.                                 if (theErr == noErr) {
  87.                                     /* and put the list in the event */
  88.                                     theErr = AEPutParamDesc(&theEvent, keyDirectObject, &theList);
  89.                                     if (theErr == noErr) {
  90.                                         /* now I'm passing the data portion of the AppleEvent to the handler */
  91.                                         /* that will open a PPC channel and pass the information along */
  92.                                         FireTheEvent(theEvent.dataHandle, storage);
  93.                                     }                       /* putparamdesc err */
  94.                                 }                           /* putDesc error */
  95.                                 /* dispose of all the appleevent strutures I've been using */
  96.                                 AEDisposeDesc(&docDesc);
  97.                             }                               /* docDesc creation error */
  98.                         }                                   /* alias creation error */
  99.                         AEDisposeDesc(&theList);
  100.                     }                                       /* list create error */
  101.                     
  102.                 }                                           /* standardfile cancel */
  103.                 AEDisposeDesc(&theEvent);
  104.             }                                               /* event create error */
  105.             AEDisposeDesc(&theAddress);
  106.         }                                                   /* desc 1 error */
  107.     }                                                       /* browser cancel or error */
  108. } /* end FindATarget */
  109.  
  110. /* FindAEBuddy searches for the port to use to send the event.  In this */
  111. /* case I'm using my AEDaemon application to send events for me.  */
  112. /* So, if first see if it's available by looking for it's port with */
  113. /* IPCListPorts.  If it isn't available, I search for it by */
  114. /* creator and file type with PBCatSearch, and launch it if I find it */
  115. /* Of course, if I launch it myself I need to give it some time */
  116. /* to register itself and come up in the PPC port list, so I'll set */
  117. /* a flag and go away for a while, checking back periodically until */
  118. /* the port comes up */
  119. /* You can use AEBuddy also for your app, though I'd change the name.... */
  120. void FindAEBuddy(CDEVHnd storage)
  121. {
  122.     Byte csState;
  123.     CDEVPtr tempPtr;
  124.     CursHandle watch;
  125.     /* Use NewPtrClear for these, so you don't have to worry about having */
  126.     /* garbage in the parameters to start */
  127.     IPCListPortsPBPtr listPtr = NewPtrClear(sizeof(IPCListPortsPBRec));
  128.     PPCPortPtr portWanted = NewPtrClear(sizeof(PPCPortRec));
  129.     LaunchParamBlockRec launchThis;
  130.     short realCount;
  131.     OSErr myError;
  132.     /* find AEBuddy, open our port, and pass the data */
  133.     /* remember NewPtrClear gave me a zeroed record, so all the parameters */
  134.     /* that I wanted nil'ed are. */
  135.     /* BY THE WAY: I could use the PPCBrowser again here, of course.  */
  136.     /* but remember, most of your users will have no idea that this CDEV is */
  137.     /* using another process, since faceless backgrounders don't show up */
  138.     /* in any list that most users can see */
  139.     watch = GetCursor(watchCursor);
  140.     SetCursor(*watch);                                      /* wait cursor */
  141.     csState = HGetState((Handle)storage);
  142.     HLock((Handle)storage);
  143.     tempPtr = *storage;                                     /* dereference this for clarity */
  144.     listPtr->requestCount = 1;                              /* only want one of them */
  145.     listPtr->portName = portWanted;
  146.     /* fill in the port a bit */
  147.     portWanted->name[0] = 1;                                /* making a "=" string here, telling IPCListPorts */
  148.     portWanted->name[1] = '=';                              /* that I don't care about the name of the port */
  149.     portWanted->portKindSelector = ppcByCreatorAndType;
  150.     portWanted->u.port.creator = 'MOOB';
  151.     portWanted->u.port.type = 'APPL';
  152.     /* the location name will be nil, since I want to get the thing on the */
  153.     /* local machine, not across the vast net */
  154.     listPtr->locationName = nil;
  155.     listPtr->bufferPtr = (PortInfoArrayPtr)NewPtrClear(sizeof(PortInfoRec));
  156.     /* we're only asking for one, so we only need one array space allocated */
  157.     
  158.     myError = IPCListPorts(listPtr, false);                 /* getting it syncronously */
  159.     realCount = listPtr->actualCount;
  160.     /* so we don't forget */
  161.     if (myError == noErr) {
  162.         if (realCount == 0 && (*storage)->searchForTarget == false) {
  163.             /* The following segment is the PBCatSearch area */
  164.             
  165.             /* Couldn't find the port and we haven't launched it ourselves yet. */
  166.             /* So, let's see if we can find the app and launch it */
  167.             /* ourselves */
  168.             /* make a pointer to the block */
  169.             CSParamPtr csBlockPtr = NewPtrClear(sizeof(CSParam));
  170.             long dirIDUnused;
  171.             Str32 nulString = "\p";
  172.             /* initialize the parameter block */
  173.             if (csBlockPtr) {
  174.                 csBlockPtr->ioSearchInfo1 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  175.                 csBlockPtr->ioSearchInfo2 = (CInfoPBPtr)NewPtrClear(sizeof(CInfoPBRec));
  176.                 if (csBlockPtr->ioSearchInfo1 && csBlockPtr->ioSearchInfo2) {
  177.                     csBlockPtr->ioMatchPtr = (FSSpecPtr)NewPtrClear(sizeof(FSSpec) * 1);        /* only looking for 1 */
  178.                     if (csBlockPtr->ioMatchPtr) {
  179.                         /* Now see if we can create an optimization buffer */
  180.                         csBlockPtr->ioOptBuffer = NewPtr(2048);
  181.                         if (csBlockPtr->ioOptBuffer)
  182.                             csBlockPtr->ioOptBufSize = 2048;
  183.                         else
  184.                             csBlockPtr->ioOptBufSize = 0;       /* no buffer, sorry */
  185.                         csBlockPtr->ioReqMatchCount = 1;
  186.                         csBlockPtr->ioSearchTime = 0;       /* no timeout */
  187.                     }
  188.                 }
  189.             }
  190.             /* check all my memory allocations here */
  191.             if (csBlockPtr->ioSearchInfo1 && csBlockPtr->ioSearchInfo2 && csBlockPtr->ioMatchPtr) {
  192.                 /* had memory, continue */
  193.                 HGetVol(nil, &csBlockPtr->ioVRefNum, &dirIDUnused);     /* get default volume for search */
  194.                 csBlockPtr->ioSearchInfo1->hFileInfo.ioNamePtr = nil;
  195.                 csBlockPtr->ioSearchInfo2->hFileInfo.ioNamePtr = nil;
  196.                 csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdCreator = 'MOOB';
  197.                 csBlockPtr->ioSearchInfo1->hFileInfo.ioFlFndrInfo.fdType = 'APPL';
  198.                 csBlockPtr->ioSearchBits = fsSBFlFndrInfo;
  199.                 csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdCreator = 0xFFFFFFFF;
  200.                 csBlockPtr->ioSearchInfo2->hFileInfo.ioFlFndrInfo.fdType = 0xFFFFFFFF;
  201.                 myError = PBCatSearch(csBlockPtr, false);       /* search sync */
  202.                 if (myError == noErr && csBlockPtr->ioActMatchCount != 0) {
  203.                 
  204.                     /* we found it, so launch it */
  205.                     launchThis.launchBlockID = extendedBlock;
  206.                     launchThis.launchEPBLength = extendedBlockLen;
  207.                     launchThis.launchFileFlags = nil;
  208.                     launchThis.launchControlFlags = launchContinue + launchNoFileFlags;
  209.                     launchThis.launchAppSpec = &csBlockPtr->ioMatchPtr[0];
  210.                     myError = LaunchApplication(&launchThis);
  211.                     if (myError == noErr) {
  212.                         /* it launched fine.  Set a flag so we can */
  213.                         /* check periodically until it's */
  214.                         /* PPC port comes up */
  215.                         (*storage)->searchForTarget = true;
  216.                     }
  217.                 } else {
  218.                     /* PBCat failed, we have no buddy on this volume.  Oh well */
  219.                     (*storage)->noBuddy = true;
  220.                 }
  221.             }                                               /* out of memory error */
  222.             if (csBlockPtr) {
  223.                 /* clean up what we allocated */
  224.                 if (csBlockPtr->ioSearchInfo1)
  225.                     DisposPtr((Ptr)csBlockPtr->ioSearchInfo1);
  226.                 if (csBlockPtr->ioSearchInfo2)
  227.                     DisposPtr((Ptr)csBlockPtr->ioSearchInfo2);
  228.                 if (csBlockPtr->ioMatchPtr)
  229.                     DisposPtr((Ptr)csBlockPtr->ioMatchPtr);
  230.                 if (csBlockPtr->ioOptBuffer)
  231.                     DisposPtr((Ptr)csBlockPtr->ioOptBuffer);
  232.                 DisposPtr((Ptr)csBlockPtr);
  233.             }
  234.             
  235.             /* catsearch section end */
  236.         } else {
  237.             PortInfoPtr portInfoTemp = (PortInfoPtr)listPtr->bufferPtr;
  238.             tempPtr->myPPCBlock->buddyPortPtr = (PPCPortPtr)NewPtrClear(sizeof(PPCPortRec));
  239.             /* we have a port to send to.  So, we'll first clear that flag... */
  240.             (*storage)->searchForTarget = false;
  241.             BlockMove((Ptr)&portInfoTemp->name, (Ptr)tempPtr->myPPCBlock->buddyPortPtr, sizeof(PPCPortRec));
  242.             
  243.         }
  244.     }                                                       /* listports err */
  245.     /* clean up the IPCListPorts memory */
  246.     if (listPtr->bufferPtr)
  247.         DisposPtr((Ptr)listPtr->bufferPtr);
  248.     if (listPtr)
  249.         DisposPtr((Ptr)listPtr);
  250.     if (portWanted)
  251.         DisposPtr((Ptr)portWanted);
  252.     
  253.     /* NOTE: I don't need to clean up listPtr->bufferPtr since I moved this into */
  254.     /* our other structure for later use */
  255.     InitCursor();
  256. } /* end FindAEBuddy */
  257.  
  258. /* FireTheEvent starts the PPC process.  It opens a port for us, and connects us to */
  259. /* AEBuddy.  The, through a series of asyncronous PPC calls, it transfers all the data */
  260. /* that makes up the APpleEvent we want to send. */
  261. void FireTheEvent(Handle packedEvent, CDEVHnd storage)
  262. {
  263.     /* all this will happen asyncronously, so no error back from this routine */
  264.     /* The first thing we do is open our own port, that completion routine will */
  265.     /* start a session with our target, that completion routine will write the data, */
  266.     /* that completion roiutine will end the session, then that completion routine */
  267.     /* will close the port.  */
  268.     /* Open our port */
  269.     /* first check to see if we've already opened a port.  If not, open one */
  270.     
  271.     Str32 myName;
  272.     PPCPortPtr myPort = (*storage)->myPPCBlock->myPort;
  273.     PPCOpenPBPtr openPtr = (PPCOpenPBPtr)(*storage)->myPPCBlock;
  274.     /* and once more, local 4 byte space is cheap */
  275.     MyPPCRecPtr ourPtr = (MyPPCRecPtr)openPtr;
  276.     GetIndString(&myName, kStringsID, kMyName);
  277.     /* take the passed handle, make it our own ptr */
  278.     ourPtr->bufferSize = GetHandleSize(packedEvent);
  279.     ourPtr->buffer = NewPtr(GetHandleSize(packedEvent));
  280.     HLock(packedEvent);
  281.     BlockMove((Ptr)*packedEvent, ourPtr->buffer, GetHandleSize(packedEvent));
  282.     /*  Create our port */
  283.     myPort->nameScript = 0;
  284.     BlockMove((Ptr)&myName, (Ptr)&myPort->name, myName[0] + 1);
  285.     myPort->portKindSelector = ppcByCreatorAndType;
  286.     myPort->u.port.creator = 'ckh1';
  287.     myPort->u.port.type = 'APPL';
  288.     openPtr->ioCompletion = (PPCCompProcPtr)OpenComplete;
  289.     
  290.     openPtr->serviceType = ppcServiceRealTime;              /* only valid one under 7.0 */
  291.     openPtr->resFlag = 0;
  292.     openPtr->portName = myPort;
  293.     openPtr->locationName = nil;
  294.     openPtr->networkVisible = false;
  295.     PPCOpen(openPtr, true);
  296.     (*storage)->eventPending = true;
  297. }
  298.  
  299. void OpenComplete(PPCStartPBPtr p)
  300. {
  301.     OSErr myErr;
  302.     /* cast this so it's easier to see */
  303.     MyPPCRecPtr ourPtr = (MyPPCRecPtr)p;
  304.     myErr = p->ioResult;
  305.     if (myErr == noErr) {
  306.         ourPtr->ourPort = p->portRefNum;
  307.        /* We opened our port successfully, so now connect to the buddy */
  308.     p->ioCompletion = (PPCCompProcPtr)StartComplete;
  309.     p->portName = ourPtr->buddyPortPtr;
  310.     p->locationName = nil;
  311.     PPCStart((PPCStartPBPtr)p, true);
  312.      } else {
  313.         DebugStr("\p error in opencomp");
  314.     }
  315. }
  316.  
  317. void StartComplete(PPCWritePBPtr p)
  318. {
  319.     OSErr fred;
  320.     MyPPCRecPtr ourPtr = (MyPPCRecPtr)p;
  321.     fred = p->ioResult;
  322.     if (fred == noErr) {
  323.     /* we started a session.  In this case, we were allowed to connect without authentication */
  324.     /* so we can start blasting data now */
  325.         p->bufferLength = ourPtr->bufferSize;
  326.         p->bufferPtr = ourPtr->buffer;
  327.         p->more = false;
  328.         /* pass ???? as the creator, the AEBuddy doesn't care who is sending it data */
  329.         p->blockCreator = kGenericCreator;
  330.         /* telling the buddy what type of data I'm sending */
  331.         /* since it _only_ accepts one type */
  332.         p->blockType = kMyTypeOfData;                       
  333.         p->ioCompletion = (PPCCompProcPtr)WriteComplete;
  334.         ourPtr->currentSessionRef = p->sessRefNum;
  335.         PPCWrite((PPCWritePBPtr)p, (Boolean)true);
  336.     } else {
  337.         DebugStr("\p error in startcomp");
  338.         p->ioCompletion = (PPCCompProcPtr)EndComplete;
  339.         PPCEnd((PPCEndPBPtr)p, true);
  340.         
  341.     }
  342. }
  343.  
  344. void WriteComplete(PPCEndPBPtr p)
  345. {
  346.     MyPPCRecPtr ourPtr = (MyPPCRecPtr)p;
  347.     OSErr fred;
  348.     fred = p->ioResult;
  349.     if (fred == noErr) {
  350.     /* We wrote everything we wanted to, time to end the session */
  351.         p->ioCompletion = (PPCCompProcPtr)EndComplete;
  352.         PPCEnd(p, true);
  353.     } else {
  354.         DebugStr("\p error in writecomp");
  355.         p->ioCompletion = (PPCCompProcPtr)EndComplete;
  356.         PPCEnd(p, true);
  357.         
  358.     }
  359. }
  360.  
  361. void EndComplete(PPCClosePBPtr p)
  362. {
  363.     MyPPCRecPtr ourPtr = (MyPPCRecPtr)p;
  364.     /* clear our session ref number please */
  365.     if (p->ioResult) {
  366.         DebugStr("\p error in endcomp");
  367.     }
  368.     /* I'm closing our port here, you could of course leave it open */
  369.     /* for repeated requests.  One reason why I'm not leaving it open is */
  370.     /* because I don't want anyone to try and talk to us */
  371.     ourPtr->currentSessionRef = nil;
  372.     /* and close the session out */
  373.     p->ioCompletion = nil;
  374.     PPCClose(p, false);
  375.     ourPtr->pB.openParam.portRefNum = nil;
  376. }
  377.  
  378.  
  379. #undef __BUILDINGCDEV__
  380.